﻿#include "EglContext.h"

EglContext::EglContext()
{
	_display = EGL_NO_DISPLAY;
	_surface = EGL_NO_SURFACE;
	_context = EGL_NO_CONTEXT;
}

EglContext::~EglContext()
{
	close();
}

int EglContext::open(EGLNativeWindowType wnd)
{
	EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE };

	const EGLint configAttribs[] = 
	{
		EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
		EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
		EGL_RED_SIZE, 8,
		EGL_GREEN_SIZE, 8,
		EGL_BLUE_SIZE, 8,
		EGL_DEPTH_SIZE, 8,
		EGL_NONE
	};

	// 获取Display
	_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);

	if (_display == EGL_NO_DISPLAY)
	{
		return -1;
	}

	EGLint majorVersion = 0;
	EGLint minorVersion = 0;
	EGLBoolean success = EGL_FALSE;

	// 初始化egl, major 和 minor 将被赋予当前 EGL 版本号.
	success = eglInitialize(_display, &majorVersion, &minorVersion);

	if (!success) {
		close();
		return -1;
	}

	EGLint configSize = 0;
	EGLConfig config = NULL;

	// 选择Config
	success = eglChooseConfig(_display, configAttribs, &config, 1, &configSize);

	if (!success || configSize <= 0) {
		close();
		return -1;
	}

	// 渲染目标
	_surface = eglCreateWindowSurface(_display, config, wnd, NULL);

	if (_surface == EGL_NO_SURFACE) {
		close();
		return -1;
	}

	// OpenGL ES 的状态机, 有当前的颜色、纹理坐标、变换矩阵、绚染模式等状态
	_context = eglCreateContext(_display, config, EGL_NO_CONTEXT, contextAttribs);

	if (_context == EGL_NO_CONTEXT) {
		close();
		return -1;
	}

	return 0;
}

void EglContext::close()
{
	if (EGL_NO_DISPLAY != _display) {
		if (eglGetCurrentContext() == _context) {
			// 确保上下文立即被删除
			eglMakeCurrent(_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
		}

		if (EGL_NO_CONTEXT != _context) {
			eglDestroyContext(_display, _context);
			_context = EGL_NO_CONTEXT;
		}

		if (EGL_NO_SURFACE != _surface) {
			eglDestroySurface(_display, _surface);
			_surface = EGL_NO_SURFACE;
		}

		eglTerminate(_display);
		_display = EGL_NO_DISPLAY;
	}
}

void EglContext::use()
{
	if (eglGetCurrentContext() == _context)
	{
		return;
	}

	// 通过eglMakeCurrent()函数来将当前的上下文切换
	eglMakeCurrent(_display, _surface, _surface, _context);
}

void EglContext::swap()
{
	// 一帧完成之后, 把帧切换到前台帧进行显示
	eglSwapBuffers(_display, _surface);
}